# -*- coding: utf-8 -*-
from __future__ import absolute_import

import sys

from PyQt4.QtGui import QApplication
from PyQt4.QtGui import QMainWindow
from PyQt4.QtGui import QMessageBox
from PyQt4.QtGui import QSplashScreen
from PyQt4.QtGui import QIcon
from PyQt4.QtGui import QPixmap
from PyQt4.QtGui import QToolBar

from PyQt4.QtCore import Qt
from PyQt4.QtCore import QSettings
from PyQt4.QtCore import QCoreApplication
from PyQt4.QtCore import QTranslator
from PyQt4.QtCore import SIGNAL
from PyQt4.QtCore import QTextCodec

from ninja_ide import resources
from ninja_ide.core import settings
from ninja_ide.core import file_manager
from ninja_ide.gui import updates
from ninja_ide.gui import actions
from ninja_ide.tools import styles
from ninja_ide.tools import json_manager
#NINJA-IDE Containers
from ninja_ide.gui import central_widget
from ninja_ide.gui.main_panel import main_container
from ninja_ide.gui.explorer import explorer_container
from ninja_ide.gui.misc import misc_container
from ninja_ide.gui import status_bar
#NINJA-IDE Menus
from ninja_ide.gui.menus import menu_about
from ninja_ide.gui.menus import menu_file
from ninja_ide.gui.menus import menu_edit
from ninja_ide.gui.menus import menu_view
from ninja_ide.gui.menus import menu_plugins
from ninja_ide.gui.menus import menu_project
from ninja_ide.gui.menus import menu_source

###############################################################################
# IDE: MAIN CONTAINER
###############################################################################
__ideInstance = None


def IDE(*args, **kw):
    global __ideInstance
    if __ideInstance is None:
        __ideInstance = __IDE(*args, **kw)
    return __ideInstance


class __IDE(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowTitle('NINJA-IDE {Ninja-IDE Is Not Just Another IDE}')
        self.setWindowIcon(QIcon(resources.IMAGES['icon']))
        self.setWindowState(Qt.WindowMaximized)
        self.setMinimumSize(700, 500)

        #Opactity
        self.opacity = settings.MAX_OPACITY

        #Define Actions object before the UI
        self._actions = actions.Actions()
        #Main Widget - Create first than everything else
        self._central = central_widget.CentralWidget(self)
        self.load_ui(self._central)
        self.setCentralWidget(self._central)

        #ToolBar
        self._toolbar = QToolBar(self)
        styles.set_style(self._toolbar, 'toolbar-default')
        self._toolbar.setToolTip(self.tr("Press and Drag to Move"))
        self._toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly)
        self.addToolBar(settings.TOOLBAR_ORIENTATION, self._toolbar)

        #StatusBar
        self._status = status_bar.StatusBar(self)
        self._status.hide()
        self.setStatusBar(self._status)

        #Install Shortcuts after the UI has been initialized
        self._actions.install_shortcuts(self)

        #Menu
        menubar = self.menuBar()
        file_ = menubar.addMenu(self.tr("&File"))
        edit = menubar.addMenu(self.tr("&Edit"))
        view = menubar.addMenu(self.tr("&View"))
        source = menubar.addMenu(self.tr("&Source"))
        project = menubar.addMenu(self.tr("&Project"))
        pluginsMenu = menubar.addMenu(self.tr("P&lugins"))
        about = menubar.addMenu(self.tr("&About"))

        #The order of the icons in the toolbar is defined by this calls
        self._menuFile = menu_file.MenuFile(file_, self._toolbar, self)
        self._menuView = menu_view.MenuView(view, self._toolbar, self)
        self._menuEdit = menu_edit.MenuEdit(edit, self._toolbar)
        self._menuSource = menu_source.MenuSource(source)
        self._menuProject = menu_project.MenuProject(project, self._toolbar)
        self._menuPlugins = menu_plugins.MenuPlugins(pluginsMenu)
        self._menuAbout = menu_about.MenuAbout(about)

        #Tray Icon
        self._trayIcon = updates.TrayIconUpdates(self)
        self._trayIcon.show()

        self.connect(self._mainContainer, SIGNAL("fileSaved(QString)"),
            self.show_status_message)

    def show_status_message(self, message):
        self._status.showMessage(message, 2000)

    def load_ui(self, centralWidget):
        #Create Main Container to manage Tabs
        self._mainContainer = main_container.MainContainer(self)
        self.connect(self._mainContainer, SIGNAL("currentTabChanged(QString)"),
            self.change_window_title)
        self.connect(self._mainContainer,
            SIGNAL("locateFunction(QString, QString, bool)"),
            self._actions.locate_function)
        #Create Explorer Panel
        self._explorer = explorer_container.ExplorerContainer(self)
        self.connect(self._central, SIGNAL("splitterCentralRotated()"),
            self._explorer.rotate_tab_position)
        #Create Misc Bottom Container
        self._misc = misc_container.MiscContainer(self)

        centralWidget.insert_central_container(self._mainContainer)
        centralWidget.insert_lateral_container(self._explorer)
        centralWidget.insert_bottom_container(self._misc)

        if settings.SHOW_START_PAGE:
            self._mainContainer.show_start_page()

    def load_session_files_projects(self, filesTab1, filesTab2, projects):
        self._mainContainer.open_files(filesTab1)
        self._mainContainer.open_files(filesTab2, False)
        self._explorer.open_session_projects(projects)
        self._status.explore_code()

    def change_window_title(self, title):
        self.setWindowTitle('NINJA-IDE - ' + title)

    def wheelEvent(self, event):
        if event.modifiers() == Qt.AltModifier:
            if event.delta() == 120 and self.opacity < settings.MAX_OPACITY:
                self.opacity += 0.1
            elif event.delta() == -120 and self.opacity > settings.MIN_OPACITY:
                self.opacity -= 0.1
            self.setWindowOpacity(self.opacity)
            event.ignore()
        else:
            QMainWindow.wheelEvent(self, event)

    def closeEvent(self, event):
        if settings.CONFIRM_EXIT and \
        self._mainContainer.check_for_unsaved_tabs():
            val = QMessageBox.question(self,
                self.tr("Some changes were not saved"),
                self.tr("Do you want to exit anyway?"),
                QMessageBox.Yes, QMessageBox.No)
            if val == QMessageBox.No:
                event.ignore()
        openedFiles = self._mainContainer.get_opened_documents()
        qsettings = QSettings()
        if qsettings.value('preferences/general/loadFiles', True):
            qsettings.setValue('openFiles/projects',
                self._explorer.get_opened_projects())
            if len(openedFiles) > 0:
                qsettings.setValue('openFiles/mainTab', openedFiles[0])
            if len(openedFiles) == 2:
                qsettings.setValue('openFiles/secondaryTab', openedFiles[1])


###############################################################################
# LOAD SETTINGS
###############################################################################


def load_settings():
    qsettings = QSettings()
    #General
    settings.TOOLBAR_ORIENTATION = qsettings.value(
        'preferences/general/toolbarOrientation', 1).toInt()[0]
    settings.LANGUAGE = unicode(qsettings.value('preferences/interface/language',
        '').toString())
    settings.SHOW_START_PAGE = qsettings.value('preferences/general/showStartPage',
        True).toBool()
    settings.CONFIRM_EXIT = qsettings.value('preferences/general/confirmExit',
        True).toBool()
    settings.UI_LAYOUT = qsettings.value('preferences/interface/uiLayout',
        0).toInt()[0]
    settings.NOTIFY_UPDATES = qsettings.value('preferences/general/notifyUpdates',
        True).toBool()
    settings.PYTHON_PATH = unicode(
        qsettings.value('preferences/execution/pythonPath',
        'python').toString())
    #EXECUTION OPTIONS
    settings.EXECUTION_OPTIONS = unicode(
        qsettings.value('preferences/execution/executionOptions',
        '').toString())
    extensions = [unicode(item.toString()) for item in qsettings.value(
        'preferences/general/supportedExtensions', []).toList()]
    if extensions:
        settings.SUPPORTED_EXTENSIONS = extensions
    settings.WORKSPACE = unicode(qsettings.value('preferences/general/workspace',
        "").toString())
    #Editor
    settings.INDENT = qsettings.value('preferences/editor/indent',
        4).toInt()[0]
    settings.MARGIN_LINE = qsettings.value('preferences/editor/marginLine',
        80).toInt()[0]
    settings.REMOVE_TRAILING_SPACES = qsettings.value(
        'preferences/editor/removeTrailingSpaces', True).toBool()
    settings.SHOW_TABS_AND_SPACES = qsettings.value(
        'preferences/editor/showTabsAndSpaces', True).toBool()
    settings.ENABLE_COMPLETION_IN_COMMENTS = qsettings.value(
        'preferences/editor/completeInComments', True).toBool()
    settings.FONT_FAMILY = unicode(qsettings.value('preferences/editor/fontFamily',
        "Monospace").toString())
    settings.FONT_SIZE = qsettings.value('preferences/editor/fontSize',
        11).toInt()[0]
    settings.HIGHLIGHT_VARIABLES = qsettings.value(
        'preferences/editor/highlightVariables', True).toBool()
    settings.HIGHLIGHT_ALL_VARIABLES = qsettings.value(
        'preferences/editor/highlightAllVariables', False).toBool()
    settings.SHOW_MARGIN_LINE = qsettings.value('preferences/editor/showMarginLine',
        True).toBool()
    settings.FIND_ERRORS = qsettings.value('preferences/editor/findErrors',
        False).toBool()
    settings.CHECK_STYLE = qsettings.value('preferences/editor/checkStyle',
        True).toBool()
    settings.CODE_COMPLETION = qsettings.value('preferences/editor/codeCompletion',
        True).toBool()
    settings.CENTER_ON_SCROLL = qsettings.value('preferences/editor/centerOnScroll',
        True).toBool()
    #Projects
    settings.SHOW_PROJECT_EXPLORER = qsettings.value(
        'preferences/interface/showProjectExplorer', True).toBool()
    settings.SHOW_SYMBOLS_LIST = qsettings.value(
        'preferences/interface/showSymbolsList', True).toBool()
    settings.SHOW_WEB_INSPECTOR = qsettings.value(
        'preferences/interface/showWebInspector', False).toBool()


###############################################################################
# START NINJA-IDE
###############################################################################


def start():
    app = QApplication(sys.argv)
    QCoreApplication.setOrganizationName('NINJA-IDE')
    QCoreApplication.setOrganizationDomain('ninja-ide.org')
    QCoreApplication.setApplicationName('NINJA-IDE')

    # Create and display the splash screen
    splash_pix = QPixmap(resources.IMAGES['splash'])
    splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
    splash.setMask(splash_pix.mask())
    splash.show()
    app.processEvents()

    #Set the codec for strings (QString)
    QTextCodec.setCodecForCStrings(QTextCodec.codecForName('utf-8'))

    #Translator
    translator = QTranslator()
    translator.load(settings.LANGUAGE)
    app.installTranslator(translator)

    #Loading Syntax
    splash.showMessage("Loading Syntax" + " - DEVELOPMENT VERSION",
        Qt.AlignRight | Qt.AlignTop, Qt.black)
    json_manager.load_syntax()

    #Read Settings
    qsettings = QSettings()
    splash.showMessage("Loading Settings" + " - DEVELOPMENT VERSION",
        Qt.AlignRight | Qt.AlignTop,
        Qt.black)
    load_settings()

    #Loading Themes
    splash.showMessage("Loading Themes" + " - DEVELOPMENT VERSION",
        Qt.AlignRight | Qt.AlignTop, Qt.black)
    scheme = unicode(qsettings.value('preferences/editor/scheme',
        "default").toString())
    if scheme != 'default':
        scheme = file_manager.create_abs_path(resources.EDITOR_SKINS,
            scheme + '.color')
        resources.CUSTOM_SCHEME = json_manager.parse(open(scheme))

    #Loading GUI
    splash.showMessage("Loading GUI" + " - DEVELOPMENT VERSION",
        Qt.AlignRight | Qt.AlignTop, Qt.black)
    ide = IDE()

    #Showing GUI
    ide.show()
    #Loading Session Files
    splash.showMessage("Loading Files and Projects" + " - DEVELOPMENT VERSION",
        Qt.AlignRight | Qt.AlignTop, Qt.black)
    mainFiles = qsettings.value('openFiles/mainTab', []).toList()
    secondaryFiles = qsettings.value('openFiles/secondaryTab', []).toList()
    projects = qsettings.value('openFiles/projects', []).toList()
    ide.load_session_files_projects(mainFiles, secondaryFiles, projects)

    splash.finish(ide)
    sys.exit(app.exec_())
